package org.example.core.elasticsearch.service;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.elasticsearch.script.mustache.SearchTemplateResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.example.core.elasticsearch.document.GoodsDocument;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class ElasticSearchService {


    @Value("${simplemall.elasticsearch-index}")
    String elasticsearchIndex;
    RestHighLevelClient restHighLevelClient;

    public ElasticSearchService(RestHighLevelClient restHighLevelClient) {
        this.restHighLevelClient = restHighLevelClient;
    }

    public void save(GoodsDocument goodsDocument) throws IOException {

        IndexRequest request = new IndexRequest(elasticsearchIndex);
        request.id(String.valueOf(goodsDocument.getId()));
        String jsonString = "{" +
                "\"name\":\"" + goodsDocument.getName() + "\"" +
                "}";

        request.source(jsonString, XContentType.JSON);
        restHighLevelClient.index(request, RequestOptions.DEFAULT);
    }

    public void delete(Long id){


    }


    public ArrayList<Map<String, Object>> query(String keyword, Integer from, Integer size, String preTags, String postTags) throws IOException{
        SearchTemplateRequest request = new SearchTemplateRequest();
        request.setRequest(new SearchRequest(elasticsearchIndex));

        request.setScriptType(ScriptType.INLINE);

        request.setScript("{\n" +
                "  \"from\": {{from}},\n" +
                "  \"size\": {{size}}, \n" +
                "  \"query\": {\n" +
                "    \"match\": {\n" +
                "      \"name\": \"{{value}}\"\n" +
                "    }\n" +
                "  },\n" +
                " \"highlight\": {\n" +
                "    \"fields\": {\n" +
                "      \"name\":{\n" +
                "         \"type\": \"unified\"\n" +
                "      }\n" +
                "    },\n" +
                "    \"pre_tags\": [\"{{preTags}}\"],\n" +
                "    \"post_tags\": [\"{{postTags}}\"]\n" +
                "    \n" +
                "  }\n" +
                "}");

        Map<String, Object> scriptParams = new HashMap<>();
        scriptParams.put("value", keyword);
        scriptParams.put("from", from);
        scriptParams.put("size", size);
        scriptParams.put("preTags", preTags);
        scriptParams.put("postTags", postTags);
        request.setScriptParams(scriptParams);

        SearchTemplateResponse searchTemplateResponse = restHighLevelClient.searchTemplate(request, RequestOptions.DEFAULT);

        ArrayList<Map<String, Object>> list = new ArrayList<>();
        for (SearchHit searchHit : searchTemplateResponse.getResponse().getHits().getHits()) {


            //解析高亮的字段
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            HighlightField title = highlightFields.get("name");
            //没有高亮时的结果
            Map<String, Object> sourceAsMap = searchHit.getSourceAsMap();

            //解析高亮的字段，将原来的字段替换为我们高亮的字段即可

            sourceAsMap.put("id", searchHit.getId());
            sourceAsMap.put("name", Stream.of(title.fragments()).map(Text::toString).collect(Collectors.joining("")));
            list.add(sourceAsMap);
        }

        return list;
    }


}
